class WeiboAlbumDownloader {
  constructor() {
    this.isCollecting = false;
    this.imageList = [];
    this.workbook = null;
    this.worksheet = null;
    this.currentRow = 1;
    this.batchSize = 1000; // 增大写入批次大小
    this.concurrentLimit = 10; // 增加并发请求数
    this.scrollInterval = 200; // 减少滚动等待时间
    this.imageBuffer = [];
    this.pendingRows = [];
    this.isWriting = false; // 写入状态标记
    this.lastPosition = 0; // 记录最后的滚动位置
    this.lastImageId = null; // 记录最后处理的图片ID
    this.processedUrls = new Set(); // 用于快速查重
    this.writeBuffer = []; // 写入缓冲区
    this.maxBufferSize = 2000; // 增大缓冲区大小
    this.lastWriteTime = Date.now();
    this.writeInterval = 5000; // 增加写入间隔
    this.crawledCount = 0; // 已爬取数量
    this.writtenCount = 0; // 已写入数量
    this.memoryBuffer = []; // 内存中的数据缓冲
    this.maxMemorySize = 5000; // 最大内存缓存数量
    this.targetCount = 2000; // 设置默认目标数量为2000
    this.selectedImages = new Set(); // 存储选中的图片ID
    this.filterPageSize = 27; // 每页显示的图片数量
    this.currentFilterPage = 1; // 当前页码
    this.filterDialogVisible = false; // 过滤对话框显示状态
    this.keyboardHandler = null; // 用于存储键盘事件监听器
    this.faceDetectionLoaded = false;
    this.faceApi = null; // 存储 face-api 实例
    this.modelLoaded = false;
    this.init();
  }

  init() {
    this.createButtons();
    this.bindEvents();
    // 确保按钮初始可见
    const btnsContainer = document.querySelector('.weibo-album-btns');
    if (btnsContainer) {
      btnsContainer.style.display = 'block';
    }
  }

  createButtons() {
    // 检查是否已存在按钮容器
    let btnContainer = document.querySelector('.weibo-album-btns');
    if (!btnContainer) {
      btnContainer = document.createElement('div');
      btnContainer.className = 'weibo-album-btns';
      btnContainer.style.display = 'block';
    }

    // 清空现有按钮
    btnContainer.innerHTML = '';

    // 创建状态栏
    const statusBar = document.createElement('div');
    statusBar.className = 'weibo-album-status';
    statusBar.id = 'statusBar';
    statusBar.style.cssText = `
      margin-bottom: 10px;
      padding: 5px;
      background-color: #f5f5f5;
      border-radius: 4px;
      font-size: 14px;
      color: #666;
    `;
    statusBar.innerHTML = `
      <div>已爬取: <span id="crawledCount">0</span> 张</div>
      <div>已写入: <span id="writtenCount">0</span> 张</div>
    `;

    const startBtn = document.createElement('button');
    startBtn.className = 'weibo-album-btn start-btn';
    startBtn.textContent = '开始爬取';
    startBtn.id = 'startCollect';

    const continueBtn = document.createElement('button');
    continueBtn.className = 'weibo-album-btn continue-btn disabled';
    continueBtn.textContent = '继续爬取';
    continueBtn.id = 'continueCollect';
    continueBtn.style.display = 'none';

    const stopBtn = document.createElement('button');
    stopBtn.className = 'weibo-album-btn stop-btn disabled';
    stopBtn.textContent = '结束爬取';
    stopBtn.id = 'stopCollect';

    const excelBtn = document.createElement('button');
    excelBtn.className = 'weibo-album-btn excel-btn disabled';
    excelBtn.textContent = '导出Excel';
    excelBtn.id = 'downloadExcel';

    const resetBtn = document.createElement('button');
    resetBtn.className = 'weibo-album-btn reset-btn';
    resetBtn.textContent = '重置';
    resetBtn.id = 'resetCollect';
    resetBtn.style.backgroundColor = '#666'; // 使用灰色区分

    // 添加目标数量输入框
    const targetInput = document.createElement('div');
    targetInput.className = 'weibo-album-target';
    targetInput.style.cssText = `
      margin: 10px 0;
      display: flex;
      align-items: center;
      gap: 10px;
    `;
    targetInput.innerHTML = `
      <label style="font-size: 14px; color: #666;">目标数量:</label>
      <input 
        type="number" 
        id="targetCount" 
        min="0" 
        value="2000"
        placeholder="0表示无限制"
        style="
          width: 100px;
          padding: 4px 8px;
          border: 1px solid #ddd;
          border-radius: 4px;
          font-size: 14px;
        "
      >
    `;

    // 添加过滤按钮
    const filterBtn = document.createElement('button');
    filterBtn.className = 'weibo-album-btn filter-btn';
    filterBtn.textContent = '过滤图片';
    filterBtn.id = 'filterImages';
    filterBtn.style.backgroundColor = '#1890ff';

    // 添加状态栏和按钮
    btnContainer.appendChild(statusBar);
    btnContainer.appendChild(targetInput);
    btnContainer.appendChild(startBtn);
    btnContainer.appendChild(continueBtn);
    btnContainer.appendChild(stopBtn);
    btnContainer.appendChild(excelBtn);
    btnContainer.appendChild(resetBtn); // 添加重置按钮
    btnContainer.appendChild(filterBtn);
    
    if (!document.querySelector('.weibo-album-btns')) {
      document.body.appendChild(btnContainer);
    }
  }

  bindEvents() {
    document.getElementById('startCollect').addEventListener('click', () => this.startCollect(true));
    document.getElementById('continueCollect').addEventListener('click', () => this.startCollect(false));
    document.getElementById('stopCollect').addEventListener('click', () => this.stopCollect());
    document.getElementById('downloadExcel').addEventListener('click', () => this.downloadExcel());
    document.getElementById('resetCollect').addEventListener('click', () => this.resetAll());
    document.getElementById('filterImages').addEventListener('click', () => this.toggleFilterDialog());
    
    // 添加输入框事件
    const targetInput = document.getElementById('targetCount');
    if (targetInput) {
      targetInput.addEventListener('change', (e) => {
        const value = parseInt(e.target.value) || 0;
        this.targetCount = Math.max(0, value); // 确保不小于0
        console.log('设置目标爬取数量:', this.targetCount);
      });
    }
  }

  initExcel() {
    // 创建新的工作簿
    this.workbook = XLSX.utils.book_new();
    
    // 创建工作表
    this.worksheet = XLSX.utils.aoa_to_sheet([['缩略图', '原图', '大小(KB)']]);
    
    // 设置列宽
    this.worksheet['!cols'] = [
      { width: 50 }, // 缩略图
      { width: 50 }, // 原图
      { width: 10 }  // 大小
    ];
    
    // 将工作表添加到工作簿
    XLSX.utils.book_append_sheet(this.workbook, this.worksheet, "微博图片列表");
  }

  async startCollect(isNewStart = true) {
    if(this.isCollecting) return;
    
    this.isCollecting = true;
    
    if (isNewStart) {
      this.imageList = [];
      this.imageBuffer = [];
      this.writeBuffer = [];
      this.currentRow = 1;
      this.lastPosition = 0;
      this.lastImageId = null;
      this.processedUrls.clear();
      this.crawledCount = 0;
      this.writtenCount = 0;
      this.initExcel();
    } else {
      if (this.lastPosition > 0) {
        window.scrollTo(0, this.lastPosition);
        await this.sleep(200);
      }
    }

    this.updateButtonStatus();
    this.startBackgroundWriter();

    while(this.isCollecting) {
      this.lastPosition = window.pageYOffset;
      const images = this.getVisibleImages();
      
      if(images.length > 0) {
        // 检查是否达到目标数量
        if (this.targetCount > 0 && this.crawledCount >= this.targetCount) {
          console.log(`已达到目标爬取数量: ${this.targetCount}`);
          await this.stopCollect();
          // 显示完成提示
          const statusBar = document.getElementById('statusBar');
          if (statusBar) {
            statusBar.innerHTML += `<div style="color: #52c41a;">✓ 已达到目标数量</div>`;
          }
          break;
        }

        // 如果有目标数量，只取需要的数量
        if (this.targetCount > 0) {
          const remaining = this.targetCount - this.crawledCount;
          if (remaining < images.length) {
            images.length = remaining;
          }
        }

        // 使用 Promise.all 并发处理图片
        const processingPromises = [];
        for (let i = 0; i < images.length; i += this.concurrentLimit) {
          const batch = images.slice(i, i + this.concurrentLimit);
          const promise = this.processNewImages(batch);
          processingPromises.push(promise);
          
          // 每批次处理完后短暂等待，避免请求过于密集
          if (processingPromises.length >= 3) {
            await Promise.all(processingPromises);
            processingPromises.length = 0;
            await this.sleep(100);
          }
        }
        
        // 处理剩余的请求
        if (processingPromises.length > 0) {
          await Promise.all(processingPromises);
        }
      }
      
      // 修改滚动逻辑
      const hasMoreContent = await this.scrollToBottom();
      if (!hasMoreContent && images.length === 0) {
        // 如果没有更多内容且没有新图片，可能已经到达底部
        console.log('已到达底部，无更多图片');
        const statusBar = document.getElementById('statusBar');
        if (statusBar) {
          statusBar.innerHTML += `<div style="color: #ff8200;">已到达底部，无更多图片</div>`;
        }
        await this.sleep(2000); // 多等待一会，确保是真的到底了
        if (this.getVisibleImages().length === 0) {
          await this.stopCollect();
          break;
        }
      }
      
      await this.sleep(this.scrollInterval);
    }
  }

  getVisibleImages() {
    try {
      const container = document.querySelector('.woo-panel-main.Card_wrap_2ibWe.ProfileAlbum_album_1RhEw');
      if(!container) {
        console.log('未找到图片容器');
        return [];
      }

      return Array.from(container.querySelectorAll('img.woo-picture-img'))
        .map(img => img.src)
        .filter(src => src.includes('sinaimg.cn'))
        .filter(src => !this.processedUrls.has(src))
        .map(src => {
          try {
            const match = src.match(/\/([^\/]+?)(?:\.jpg|@.*)?$/);
            if (!match) return null;
            this.processedUrls.add(src);
            return match[1];
          } catch (error) {
            console.error('处理图片URL时出错:', error);
            return null;
          }
        })
        .filter(Boolean);
    } catch (error) {
      console.error('获取可见图片时出错:', error);
      return [];
    }
  }

  async scrollToBottom() {
    window.scrollTo(0, document.body.scrollHeight);
    await this.sleep(500);

    // 检查并点击"加载更多"按钮或重试按钮
    const container = document.querySelector('.woo-panel-main.Card_wrap_2ibWe.ProfileAlbum_album_1RhEw');
    if (container) {
      // 先检查是否有网络异常重试按钮
      const retryBtn = container.querySelector('.next-page.woo-box-flex.woo-box-alignCenter.woo-box-justifyCenter .m-tips.m-tips-tp.cursor');
      if (retryBtn && retryBtn.textContent.includes('网络异常')) {
        try {
          console.log('检测到网络异常，点击重试');
          retryBtn.click();
          // 等待较长时间让网络恢复
          await this.sleep(2000);
          return true; // 返回true表示需要继续尝试
        } catch (error) {
          console.error('点击重试按钮失败:', error);
        }
      }

      // 检查普通的加载更多按钮
      const nextPageBtn = container.querySelector('.next-page.woo-box-flex.woo-box-alignCenter.woo-box-justifyCenter');
      if (nextPageBtn && !nextPageBtn.querySelector('.m-tips')) {
        try {
          nextPageBtn.click();
          // 等待新内容加载
          await this.sleep(1000);
          return true; // 返回true表示点击了加载更多
        } catch (error) {
          console.error('点击加载更多按钮失败:', error);
        }
      }
    }

    return false; // 返回false表示没有更多内容或按钮不可点击
  }

  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  async processNewImages(imageIds) {
    const promises = imageIds.map(async imageId => {
      try {
        const thumbnailUrl = `https://wx2.sinaimg.cn/orj360/${imageId}.jpg`;
        const directUrl = `https://wx2.sinaimg.cn/large/${imageId}.jpg`;
        
        const size = await this.getImageSize(directUrl);
        
        if (size !== '0') {
          this.writeBuffer.push([thumbnailUrl, directUrl, `${size}KB`]);
          this.crawledCount++;
          this.updateStatus();

          if (this.writeBuffer.length >= this.maxBufferSize) {
            await this.flushWriteBuffer();
          }
        }
      } catch(err) {
        console.error('Failed to process image:', imageId, err);
      }
    });

    await Promise.all(promises);
  }

  async startBackgroundWriter() {
    if (this.isWriting) return;
    this.isWriting = true;
    this.lastWriteTime = Date.now();

    const writeLoop = async () => {
      while (this.isWriting) {
        const currentTime = Date.now();
        const shouldWrite = 
          this.writeBuffer.length >= this.batchSize || // 达到批次大小
          (this.writeBuffer.length > 0 && !this.isCollecting) || // 停止收集但还有数据
          (this.writeBuffer.length > 0 && currentTime - this.lastWriteTime >= this.writeInterval); // 达到时间间隔

        if (shouldWrite) {
          const batchSize = Math.min(this.writeBuffer.length, this.batchSize);
          const batch = this.writeBuffer.splice(0, batchSize);
          
          await this.writeToExcel(batch);
          this.lastWriteTime = Date.now();
          
          // 强制更新状态
          requestAnimationFrame(() => this.updateStatus());
        }
        
        await this.sleep(100);
      }
    };

    writeLoop();
  }

  async writeToExcel(rows) {
    if (!rows.length) return;

    try {
      // 使用内存缓冲区
      this.memoryBuffer.push(...rows);
      
      // 如果内存缓冲区超过最大大小，写入一部分到Excel
      if (this.memoryBuffer.length >= this.maxMemorySize) {
        const batchToWrite = this.memoryBuffer.splice(0, this.batchSize);
        
        // 使用优化的写入方法
        const range = {
          s: { c: 0, r: this.currentRow },
          e: { c: 2, r: this.currentRow + batchToWrite.length - 1 }
        };
        
        const wsData = {};
        batchToWrite.forEach((row, idx) => {
          row.forEach((cell, col) => {
            const ref = XLSX.utils.encode_cell({ r: this.currentRow + idx, c: col });
            wsData[ref] = { v: cell, t: 's' };
          });
        });
        
        this.worksheet['!ref'] = XLSX.utils.encode_range({
          s: { c: 0, r: 0 },
          e: { c: 2, r: Math.max(this.currentRow + batchToWrite.length - 1, 1) }
        });
        
        Object.assign(this.worksheet, wsData);
        
        this.currentRow += batchToWrite.length;
        this.writtenCount += batchToWrite.length;
        
        // 强制更新状态
        requestAnimationFrame(() => this.updateStatus());
      }
    } catch (error) {
      console.error('Failed to write to Excel:', error);
      this.writeBuffer.unshift(...rows);
    }
  }

  updateStatus() {
    const crawledCountEl = document.getElementById('crawledCount');
    const writtenCountEl = document.getElementById('writtenCount');
    const excelBtn = document.getElementById('downloadExcel');
    const pendingData = this.writeBuffer.length + this.memoryBuffer.length;

    if (crawledCountEl) {
      crawledCountEl.textContent = this.crawledCount;
    }
    if (writtenCountEl) {
      writtenCountEl.textContent = this.writtenCount;
      if (pendingData > 0) {
        writtenCountEl.title = `待写入: ${pendingData}条`;
        writtenCountEl.style.color = '#ff8200';
      } else {
        writtenCountEl.title = '';
        writtenCountEl.style.color = '';
      }
    }
    if (excelBtn) {
      if (pendingData > 0) {
        excelBtn.textContent = `导出Excel(${this.writtenCount}张 + ${pendingData}待写入)`;
      } else {
        excelBtn.textContent = `导出Excel(${this.writtenCount}张)`;
      }
    }

    // 添加调试日志
    console.log(`状态更新 - 已爬取: ${this.crawledCount}, 已写入: ${this.writtenCount}, 待写入: ${pendingData}`);

    // 添加目标数量信息
    if (this.targetCount > 0) {
      console.log(`进度: ${this.crawledCount}/${this.targetCount}`);
    }
  }

  async stopCollect() {
    if(!this.isCollecting) return;
    
    this.isCollecting = false;
    
    // 显示等待提示
    const statusBar = document.getElementById('statusBar');
    if (statusBar) {
      statusBar.innerHTML += `<div id="writeStatus" style="color: #ff8200;">正在写入剩余数据...</div>`;
    }
    
    // 等待所有数据写入完成
    await this.flushWriteBuffer();
    
    // 移除等待提示
    const writeStatus = document.getElementById('writeStatus');
    if (writeStatus) {
      writeStatus.remove();
    }
    
    this.isWriting = false;
    
    const continueBtn = document.getElementById('continueCollect');
    if (continueBtn) {
      continueBtn.style.display = 'inline-block';
      continueBtn.classList.remove('disabled');
      continueBtn.disabled = false;
    }
    
    console.log('Total images found:', this.crawledCount);
    console.log('Total images written:', this.writtenCount);
    console.log('Last scroll position:', this.lastPosition);
    console.log('Last image ID:', this.lastImageId);
    
    this.updateButtonStatus();
  }

  async downloadExcel() {
    if(this.writtenCount === 0) return;

    // 计算未写入数据总量
    const pendingData = this.writeBuffer.length + this.memoryBuffer.length;
    const tolerance = 100; // 允许的误差范围

    if (pendingData > tolerance) {
      const remainingCount = pendingData;
      alert(`还有${remainingCount}条数据正在写入，请等待写入完成后再下载`);
      return;
    }

    try {
      const excelBtn = document.getElementById('downloadExcel');
      if (excelBtn) {
        excelBtn.textContent = '准备导出...';
        excelBtn.disabled = true;
      }

      // 如果有少量未写入数据，强制写入
      if (pendingData > 0) {
        const statusBar = document.getElementById('statusBar');
        if (statusBar) {
          statusBar.innerHTML += `<div id="writeStatus" style="color: #ff8200;">正在写入剩余${pendingData}条数据...</div>`;
        }
        
        await this.flushWriteBuffer();
        
        const writeStatus = document.getElementById('writeStatus');
        if (writeStatus) {
          writeStatus.remove();
        }
      }

      XLSX.writeFile(this.workbook, `weibo_images_${Date.now()}.xlsx`);

      if (excelBtn) {
        excelBtn.textContent = `导出Excel(${this.writtenCount}张)`;
        excelBtn.disabled = false;
      }

    } catch (error) {
      console.error('Export failed:', error);
      alert('导出失败，请重试');
      if (excelBtn) {
        excelBtn.textContent = `导出Excel(${this.writtenCount}张)`;
        excelBtn.disabled = false;
      }
    }
  }

  async getImageSize(url) {
    const maxRetries = 2; // 减少重试次数
    let retryCount = 0;

    while (retryCount < maxRetries) {
      try {
        const response = await fetch(url, {
          method: 'HEAD', // 使用 HEAD 请求代替 GET，减少数据传输
          headers: {
            'Referer': 'https://weibo.com/',
            'User-Agent': navigator.userAgent
          }
        });

        if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);

        const size = response.headers.get('content-length');
        if (!size) throw new Error('No content-length header');

        const sizeInKB = Math.round(parseInt(size) / 1024);
        return sizeInKB.toString();

      } catch (err) {
        retryCount++;
        if (retryCount === maxRetries) return '0';
        await this.sleep(500 * retryCount);
      }
    }

    return '0';
  }

  updateButtonStatus() {
    const startBtn = document.getElementById('startCollect');
    const continueBtn = document.getElementById('continueCollect');
    const stopBtn = document.getElementById('stopCollect');
    const excelBtn = document.getElementById('downloadExcel');
    const resetBtn = document.getElementById('resetCollect'); // 添加重置按钮

    if (startBtn && continueBtn && stopBtn && excelBtn && resetBtn) {
      const hasData = this.currentRow > 1 || this.writeBuffer.length > 0;
      const canContinue = !this.isCollecting && this.lastPosition > 0;
      
      startBtn.disabled = this.isCollecting;
      continueBtn.disabled = this.isCollecting || !canContinue;
      stopBtn.disabled = !this.isCollecting;
      excelBtn.disabled = !hasData;

      startBtn.classList.toggle('disabled', this.isCollecting);
      continueBtn.classList.toggle('disabled', this.isCollecting || !canContinue);
      stopBtn.classList.toggle('disabled', !this.isCollecting);
      excelBtn.classList.toggle('disabled', !hasData);

      startBtn.style.opacity = this.isCollecting ? '0.5' : '1';
      continueBtn.style.opacity = (this.isCollecting || !canContinue) ? '0.5' : '1';
      stopBtn.style.opacity = this.isCollecting ? '1' : '0.5';
      excelBtn.style.opacity = hasData ? '1' : '0.5';

      startBtn.style.backgroundColor = this.isCollecting ? '#ccc' : '#ff8200';
      continueBtn.style.backgroundColor = (this.isCollecting || !canContinue) ? '#ccc' : '#ff8200';
      stopBtn.style.backgroundColor = this.isCollecting ? '#ff8200' : '#ccc';
      excelBtn.style.backgroundColor = hasData ? '#ff8200' : '#ccc';

      // 只在停止后且有上次位置时显示继续按钮
      continueBtn.style.display = canContinue ? 'inline-block' : 'none';

      // 更新重置按钮状态
      resetBtn.disabled = this.isCollecting;
      resetBtn.classList.toggle('disabled', this.isCollecting);
      resetBtn.style.opacity = this.isCollecting ? '0.5' : '1';
      resetBtn.style.backgroundColor = this.isCollecting ? '#ccc' : '#666';
    }
  }

  async flushWriteBuffer() {
    if (this.writeBuffer.length === 0 && this.memoryBuffer.length === 0) return;

    try {
      // 先处理写入缓冲区
      if (this.writeBuffer.length > 0) {
        const batch = this.writeBuffer.splice(0, this.writeBuffer.length);
        this.memoryBuffer.push(...batch);
      }

      // 处理内存缓冲区
      if (this.memoryBuffer.length > 0) {
        const wsData = {};
        this.memoryBuffer.forEach((row, idx) => {
          row.forEach((cell, col) => {
            const ref = XLSX.utils.encode_cell({ r: this.currentRow + idx, c: col });
            wsData[ref] = { v: cell, t: 's' };
          });
        });
        
        this.worksheet['!ref'] = XLSX.utils.encode_range({
          s: { c: 0, r: 0 },
          e: { c: 2, r: Math.max(this.currentRow + this.memoryBuffer.length - 1, 1) }
        });
        
        Object.assign(this.worksheet, wsData);
        
        this.currentRow += this.memoryBuffer.length;
        this.writtenCount += this.memoryBuffer.length;
        this.memoryBuffer = [];
        this.updateStatus();
      }
    } catch (error) {
      console.error('Failed to flush buffers:', error);
      // 出错时保留数据
      this.writeBuffer.unshift(...this.memoryBuffer);
      this.memoryBuffer = [];
    }

    this.lastWriteTime = Date.now();
  }

  async resetAll() {
    if (this.isCollecting) {
      alert('请先停止爬取');
      return;
    }

    if (this.writeBuffer.length > 0 || this.memoryBuffer.length > 0) {
      const confirm = window.confirm('还有未写入的数据，确定要重置吗？');
      if (!confirm) return;
    }

    // 重置所有状态
    this.isCollecting = false;
    this.imageList = [];
    this.workbook = null;
    this.worksheet = null;
    this.currentRow = 1;
    this.imageBuffer = [];
    this.writeBuffer = [];
    this.memoryBuffer = [];
    this.pendingRows = [];
    this.isWriting = false;
    this.lastPosition = 0;
    this.lastImageId = null;
    this.processedUrls.clear();
    this.crawledCount = 0;
    this.writtenCount = 0;
    this.selectedImages.clear();
    this.currentFilterPage = 1;
    
    // 重新初始化Excel
    this.initExcel();
    
    // 更新UI
    const crawledCountEl = document.getElementById('crawledCount');
    const writtenCountEl = document.getElementById('writtenCount');
    if (crawledCountEl) crawledCountEl.textContent = '0';
    if (writtenCountEl) {
      writtenCountEl.textContent = '0';
      writtenCountEl.title = '';
      writtenCountEl.style.color = '';
    }
    
    // 更新按钮状态
    const excelBtn = document.getElementById('downloadExcel');
    const continueBtn = document.getElementById('continueCollect');
    if (excelBtn) {
      excelBtn.textContent = '导出Excel';
      excelBtn.disabled = true;
      excelBtn.classList.add('disabled');
    }
    if (continueBtn) {
      continueBtn.style.display = 'none';
      continueBtn.classList.add('disabled');
    }
    
    // 移除任何状态提示
    const writeStatus = document.getElementById('writeStatus');
    if (writeStatus) writeStatus.remove();
    
    this.updateButtonStatus();
    
    // 重置目标数量输入框为默认值2000
    const targetInput = document.getElementById('targetCount');
    if (targetInput) {
      targetInput.value = '2000';
      this.targetCount = 2000;
    }
    
    // 移除键盘事件监听器
    if (this.keyboardHandler) {
      document.removeEventListener('keydown', this.keyboardHandler);
      this.keyboardHandler = null;
    }
    
    console.log('已重置所有数据');
  }

  // 创建过滤对话框
  createFilterDialog() {
    let dialog = document.getElementById('filterDialog');
    if (!dialog) {
      dialog = document.createElement('div');
      dialog.id = 'filterDialog';
      dialog.style.cssText = `
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 80%;
        height: 80%;
        background: white;
        box-shadow: 0 0 10px rgba(0,0,0,0.3);
        z-index: 10000;
        border-radius: 8px;
        display: none;
        flex-direction: column;
      `;

      dialog.innerHTML = `
        <div style="padding: 16px; border-bottom: 1px solid #eee; display: flex; justify-content: space-between; align-items: center;">
          <h3 style="margin: 0;">图片过滤</h3>
          <div>已选择: <span id="selectedCount">0</span> 张</div>
          <button id="closeFilterDialog" style="border: none; background: none; cursor: pointer;">✕</button>
        </div>
        <div id="filterContent" style="flex: 1; overflow-y: auto; padding: 16px;">
          <div id="imageGrid" style="
            display: grid;
            grid-template-columns: repeat(9, 1fr);
            gap: 16px;
            min-height: calc(100% - 32px);
          "></div>
        </div>
        <div style="padding: 16px; border-top: 1px solid #eee; display: flex; justify-content: space-between; align-items: center;">
          <div>
            <button id="selectAll" class="weibo-album-btn" style="padding: 4px 8px; font-size: 12px;">全选</button>
            <button id="invertSelection" class="weibo-album-btn" style="padding: 4px 8px; font-size: 12px;">反选</button>
          </div>
          <div id="pagination" style="display: flex; gap: 8px; align-items: center;">
            <button class="page-btn" data-action="first">首页</button>
            <button class="page-btn" data-action="prev">上一页</button>
            <div class="page-numbers" style="display: flex; gap: 4px;"></div>
            <button class="page-btn" data-action="next">下一页</button>
            <button class="page-btn" data-action="last">末页</button>
            <div style="margin-left: 8px; display: flex; align-items: center; gap: 4px;">
              <input type="number" id="pageJump" min="1" style="width: 50px; padding: 2px 4px;">
              <button class="page-btn" data-action="jump">跳转</button>
            </div>
          </div>
          <div style="display: flex; gap: 8px;">
            <button id="faceDetection" style="padding: 4px 12px; font-size: 12px; background-color: #722ed1; color: white; border: none; border-radius: 4px; cursor: pointer;">人脸检测</button>
            <button id="exportSelected" style="padding: 4px 12px; font-size: 12px; background-color: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer;">导出所选</button>
          </div>
        </div>
      `;

      document.body.appendChild(dialog);

      // 绑定事件
      dialog.querySelector('#closeFilterDialog').addEventListener('click', () => this.toggleFilterDialog());
      dialog.querySelector('#selectAll').addEventListener('click', () => this.selectAllImages());
      dialog.querySelector('#invertSelection').addEventListener('click', () => this.invertImageSelection());
      dialog.querySelector('#exportSelected').addEventListener('click', () => this.exportSelectedImages());
      dialog.querySelector('#faceDetection').addEventListener('click', () => this.startFaceDetection());
      
      // 绑定分页事件
      dialog.querySelectorAll('.page-btn').forEach(btn => {
        btn.addEventListener('click', (e) => {
          const action = e.target.dataset.action;
          if (action === 'jump') {
            const page = parseInt(dialog.querySelector('#pageJump').value);
            if (page) this.goToPage(page);
          } else {
            this.handlePageAction(action);
          }
        });
      });
    }
    return dialog;
  }

  // 切换过滤对话框显示状态
  toggleFilterDialog() {
    const dialog = this.createFilterDialog();
    this.filterDialogVisible = !this.filterDialogVisible;
    dialog.style.display = this.filterDialogVisible ? 'flex' : 'none';
    
    if (this.filterDialogVisible) {
      this.loadFilterImages();
      // 添加键盘事件监听器
      this.keyboardHandler = (e) => {
        if (!this.filterDialogVisible) return;
        switch (e.key) {
          case 'ArrowLeft':
            e.preventDefault();
            this.handlePageAction('prev');
            break;
          case 'ArrowRight':
            e.preventDefault();
            this.handlePageAction('next');
            break;
          case 'Escape':
            e.preventDefault();
            this.toggleFilterDialog();
            break;
        }
      };
      document.addEventListener('keydown', this.keyboardHandler);
    } else {
      // 移除键盘事件监听器
      if (this.keyboardHandler) {
        document.removeEventListener('keydown', this.keyboardHandler);
      }
    }
  }

  // 加载图片到过滤对话框
  loadFilterImages() {
    const grid = document.getElementById('imageGrid');
    grid.innerHTML = '';
    
    const startIndex = (this.currentFilterPage - 1) * this.filterPageSize;
    const endIndex = startIndex + this.filterPageSize;
    const totalPages = Math.ceil((this.currentRow - 1) / this.filterPageSize);

    // 获取当前页的图片数据
    const pageData = Array.from({ length: this.currentRow - 1 }, (_, i) => {
      const ref = XLSX.utils.encode_cell({ r: i + 1, c: 0 });
      return this.worksheet[ref]?.v;
    }).slice(startIndex, endIndex);

    // 如果是首次打开对话框，将所有图片ID添加到选中集合中
    if (this.selectedImages.size === 0) {
      Array.from({ length: this.currentRow - 1 }, (_, i) => {
        const ref = XLSX.utils.encode_cell({ r: i + 1, c: 0 });
        const thumbnailUrl = this.worksheet[ref]?.v;
        if (thumbnailUrl) {
          const match = thumbnailUrl.match(/\/([^\/]+?)(?:\.jpg|@.*)?$/);
          if (match) {
            this.selectedImages.add(match[1]);
          }
        }
      });
    }

    // 填充空白格子
    while (pageData.length < this.filterPageSize) {
      pageData.push(null);
    }

    // 创建图片网格
    pageData.forEach((thumbnailUrl, index) => {
      const container = document.createElement('div');
      container.style.cssText = `
        position: relative;
        text-align: center;
        aspect-ratio: 1;
        background-color: #f5f5f5;
        border-radius: 4px;
        cursor: pointer;
        width: 100%;
        max-width: 150px; // 限制最大宽度
        margin: 0 auto; // 居中显示
      `;

      if (thumbnailUrl) {
        const imageId = thumbnailUrl.match(/\/([^\/]+?)(?:\.jpg|@.*)?$/)[1];
        const img = document.createElement('img');
        img.src = thumbnailUrl;
        img.style.cssText = `
          width: 100%;
          height: 100%;
          object-fit: cover;
          border-radius: 4px;
          transition: transform 0.2s;
        `;

        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.checked = this.selectedImages.has(imageId);
        checkbox.style.cssText = `
          position: absolute;
          bottom: 8px;
          right: 8px;
          width: 20px;
          height: 20px;
          pointer-events: none;
        `;
        checkbox.dataset.imageId = imageId; // 添加图片ID属性用于后续查找

        container.appendChild(img);
        container.appendChild(checkbox);

        // 点击图片区域切换选中状态
        container.addEventListener('click', () => {
          checkbox.checked = !checkbox.checked;
          if (checkbox.checked) {
            this.selectedImages.add(imageId);
          } else {
            this.selectedImages.delete(imageId);
          }
          this.updateSelectedCount();
        });

        // 添加悬停效果
        container.addEventListener('mouseenter', () => {
          img.style.transform = 'scale(1.05)';
        });

        container.addEventListener('mouseleave', () => {
          img.style.transform = 'scale(1)';
        });
      }

      grid.appendChild(container);
    });

    this.updatePagination(totalPages);
    this.updateSelectedCount();
  }

  // 更新分页
  updatePagination(totalPages) {
    const pagination = document.getElementById('pagination');
    const pageNumbers = pagination.querySelector('.page-numbers');
    pageNumbers.innerHTML = '';

    // 更新按钮状态
    pagination.querySelectorAll('.page-btn').forEach(btn => {
      const action = btn.dataset.action;
      if (action === 'first' || action === 'prev') {
        btn.disabled = this.currentFilterPage === 1;
      } else if (action === 'next' || action === 'last') {
        btn.disabled = this.currentFilterPage === totalPages;
      }
    });

    // 生成页码按钮
    const createPageButton = (page) => {
      const btn = document.createElement('button');
      btn.textContent = page;
      btn.className = 'page-btn' + (page === this.currentFilterPage ? ' active' : '');
      btn.style.cssText = `
        padding: 2px 8px;
        border: 1px solid #ddd;
        background: ${page === this.currentFilterPage ? '#1890ff' : 'white'};
        color: ${page === this.currentFilterPage ? 'white' : 'black'};
        cursor: pointer;
        border-radius: 4px;
      `;
      btn.addEventListener('click', () => this.goToPage(page));
      return btn;
    };

    // 显示当前页前后3页
    let startPage = Math.max(1, this.currentFilterPage - 3);
    let endPage = Math.min(totalPages, this.currentFilterPage + 3);

    if (startPage > 1) {
      pageNumbers.appendChild(createPageButton(1));
      if (startPage > 2) pageNumbers.appendChild(document.createTextNode('...'));
    }

    for (let i = startPage; i <= endPage; i++) {
      pageNumbers.appendChild(createPageButton(i));
    }

    if (endPage < totalPages) {
      if (endPage < totalPages - 1) pageNumbers.appendChild(document.createTextNode('...'));
      pageNumbers.appendChild(createPageButton(totalPages));
    }

    // 更新跳转输入框
    const pageJump = document.getElementById('pageJump');
    pageJump.value = this.currentFilterPage;
    pageJump.max = totalPages;
  }

  // 更新选中数量
  updateSelectedCount() {
    const countElement = document.getElementById('selectedCount');
    if (countElement) {
      countElement.textContent = this.selectedImages.size;
    }
  }

  // 全选
  selectAllImages() {
    const checkboxes = document.querySelectorAll('#imageGrid input[type="checkbox"]');
    checkboxes.forEach(checkbox => {
      checkbox.checked = true;
      const imageId = checkbox.closest('div').querySelector('img').src.match(/\/([^\/]+?)(?:\.jpg|@.*)?$/)[1];
      this.selectedImages.add(imageId);
    });
    this.updateSelectedCount();
  }

  // 反选
  invertImageSelection() {
    const checkboxes = document.querySelectorAll('#imageGrid input[type="checkbox"]');
    checkboxes.forEach(checkbox => {
      checkbox.checked = !checkbox.checked;
      const imageId = checkbox.closest('div').querySelector('img').src.match(/\/([^\/]+?)(?:\.jpg|@.*)?$/)[1];
      if (checkbox.checked) {
        this.selectedImages.add(imageId);
      } else {
        this.selectedImages.delete(imageId);
      }
    });
    this.updateSelectedCount();
  }

  // 导出选中的图片
  async exportSelectedImages() {
    if (this.selectedImages.size === 0) {
      alert('请先选择要导出的图片');
      return;
    }

    // 创建新的工作簿
    const newWorkbook = XLSX.utils.book_new();
    const newWorksheet = XLSX.utils.aoa_to_sheet([['缩略图', '原图', '大小(KB)']]);

    // 收集选中图片的数据
    let currentRow = 1;
    for (let i = 1; i < this.currentRow; i++) {
      const thumbnailRef = XLSX.utils.encode_cell({ r: i, c: 0 });
      const thumbnailUrl = this.worksheet[thumbnailRef]?.v;
      const imageId = thumbnailUrl.match(/\/([^\/]+?)(?:\.jpg|@.*)?$/)[1];

      if (this.selectedImages.has(imageId)) {
        const originalRef = XLSX.utils.encode_cell({ r: i, c: 1 });
        const sizeRef = XLSX.utils.encode_cell({ r: i, c: 2 });
        
        XLSX.utils.sheet_add_aoa(newWorksheet, [[
          thumbnailUrl,
          this.worksheet[originalRef]?.v,
          this.worksheet[sizeRef]?.v
        ]], { origin: currentRow });
        
        currentRow++;
      }
    }

    // 设置列宽
    newWorksheet['!cols'] = [
      { width: 50 },
      { width: 50 },
      { width: 10 }
    ];

    XLSX.utils.book_append_sheet(newWorkbook, newWorksheet, "已筛选的微博图片");
    XLSX.writeFile(newWorkbook, `weibo_filtered_images_${Date.now()}.xlsx`);
  }

  // 添加页面跳转相关方法
  handlePageAction(action) {
    const totalPages = Math.ceil((this.currentRow - 1) / this.filterPageSize);
    switch (action) {
      case 'first':
        this.goToPage(1);
        break;
      case 'prev':
        this.goToPage(Math.max(1, this.currentFilterPage - 1));
        break;
      case 'next':
        this.goToPage(Math.min(totalPages, this.currentFilterPage + 1));
        break;
      case 'last':
        this.goToPage(totalPages);
        break;
    }
  }

  goToPage(page) {
    const totalPages = Math.ceil((this.currentRow - 1) / this.filterPageSize);
    if (page >= 1 && page <= totalPages && page !== this.currentFilterPage) {
      this.currentFilterPage = page;
      this.loadFilterImages();
    }
  }

  // 修改 startFaceDetection 方法
  async startFaceDetection() {
    const faceDetectionBtn = document.getElementById('faceDetection');
    if (!faceDetectionBtn) return;

    try {
      faceDetectionBtn.textContent = '检测中...';
      faceDetectionBtn.disabled = true;

      // 添加进度提示
      const progressDiv = document.createElement('div');
      progressDiv.style.cssText = `
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        background: rgba(0, 0, 0, 0.8);
        color: white;
        padding: 20px;
        border-radius: 8px;
        z-index: 10001;
      `;
      progressDiv.textContent = '开始人脸检测...';
      document.body.appendChild(progressDiv);

      // 获取所有选中的图片
      const selectedImages = Array.from(this.selectedImages);
      const totalImages = selectedImages.length;
      let processedCount = 0;
      let singleFaceCount = 0;

      // 批量处理图片
      const batchSize = 5;
      for (let i = 0; i < selectedImages.length; i += batchSize) {
        const batch = selectedImages.slice(i, Math.min(i + batchSize, selectedImages.length));
        const promises = batch.map(async imageId => {
          try {
            const imageUrl = `https://wx2.sinaimg.cn/orj360/${imageId}.jpg`;
            const result = await chrome.runtime.sendMessage({
              type: 'detectFaces',
              imageUrl,
              imageId
            });

            if (result.success) {
              const checkbox = document.querySelector(`input[type="checkbox"][data-image-id="${imageId}"]`);
              if (result.faceCount > 0) {  // 只要检测到人脸就保留
                singleFaceCount++;
              } else {
                this.selectedImages.delete(imageId);
                if (checkbox) checkbox.checked = false;
              }

              // 添加检测结果标记
              const imgContainer = checkbox?.closest('.image-container');
              if (imgContainer) {
                const badge = document.createElement('div');
                badge.style.cssText = `
                  position: absolute;
                  top: 5px;
                  right: 5px;
                  padding: 2px 6px;
                  border-radius: 10px;
                  font-size: 12px;
                  color: white;
                  background-color: ${result.faceCount > 0 ? '#52c41a' : '#f5222d'};
                `;
                badge.textContent = `${result.faceCount}张脸`;
                imgContainer.style.position = 'relative';
                imgContainer.appendChild(badge);
              }
            }
          } catch (error) {
            console.error('人脸检测失败:', imageId, error);
          }

          processedCount++;
          progressDiv.textContent = `正在检测: ${processedCount}/${totalImages} (已找到${singleFaceCount}张单人照)`;
        });

        await Promise.all(promises);
        await new Promise(resolve => setTimeout(resolve, 500));
      }

      // 清理和更新 UI
      progressDiv.remove();
      this.updateSelectedCount();
      this.loadFilterImages();

      faceDetectionBtn.textContent = '人脸检测';
      faceDetectionBtn.disabled = false;

      alert(`检测完成！\n共检测 ${totalImages} 张图片\n保留了 ${singleFaceCount} 张单人照片`);

    } catch (error) {
      console.error('人脸检测过程出错:', error);
      alert('人脸检测过程出错，请重试');
      faceDetectionBtn.textContent = '人脸检测';
      faceDetectionBtn.disabled = false;
    }
  }
}

// 防止重复初始化
if (!window.weiboAlbumDownloader) {
  window.weiboAlbumDownloader = new WeiboAlbumDownloader();
} 